gtk-demo: Support keywords for search
authorMatthias Clasen <mclasen@redhat.com>
Sun, 13 Sep 2020 15:37:23 +0000 (11:37 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Sun, 13 Sep 2020 19:00:14 +0000 (15:00 -0400)
Filter the sidebar on keywords that can be provided
by the demos. We extract keywords from the doc comment
at the top of each demo source by looking for words that
look like class names. We also allow to specify keywords
explicitly.

demos/gtk-demo/geninclude.py
demos/gtk-demo/main.c

index bae6e57f47085520f86cd89864a430eb1b28e748..2ebfaeb62580889965e09c52dd381c3b0c38f217 100755 (executable)
@@ -6,6 +6,22 @@ import re
 import os
 from collections import *
 
+def add_quotes(s):
+    return "\"" + s.lower() + "\""
+
+def wordify(s):
+    return s.strip().rstrip(".,;:")
+
+def is_keyword(s):
+    if s == "GTK":
+      return False
+    elif s.startswith(("Gtk", "Gdk", "Pango")):
+        return True
+    elif s.startswith("G") and s[1].isupper():
+        return True
+    else:
+        return False
+
 out_file = sys.argv[1]
 in_files = sys.argv[2:]
 
@@ -19,13 +35,14 @@ struct _DemoData
 {
   const char *name;
   const char *title;
+  const char **keywords;
   const char *filename;
   GDoDemoFunc func;
   DemoData *children;
 };
 """
 
-# Demo = namedtuple('Demo', ['name', 'title', 'file', 'func'])
+# Demo = namedtuple('Demo', ['name', 'title', 'keywords', 'file', 'func'])
 
 demos = []
 
@@ -34,14 +51,17 @@ for demo_file in in_files:
     demo_name = filename.replace(".c", "")
     with open(demo_file, 'r', encoding='utf-8') as f:
         title = f.readline().replace("/*", "").strip()
-
+        keywords = set()
+        line = f.readline().strip();
+        while not line.endswith('*/'):
+            if line.startswith("* #Keywords:"):
+                keywords = keywords.union(set(map(wordify, line.replace ("* #Keywords:", "").strip().split(","))))
+            else:
+                keywords = keywords.union(set(filter(is_keyword, map(wordify, line.replace ("* ", "").split()))))
+            line = f.readline().strip()
 
     file_output += "GtkWidget *do_" + demo_name + " (GtkWidget *do_widget);\n"
-    # demos += Demo(name = demo_name,
-                  # title = title,
-                  # file = demo_file,
-                  # func = "do_" + title)
-    demos.append((demo_name, title, filename, "do_" + demo_name, -1))
+    demos.append((demo_name, title, keywords, filename, "do_" + demo_name, -1))
 
 # Generate a List of "Parent names"
 parents = []
@@ -57,7 +77,7 @@ for demo in demos:
         if not parent_name in parents:
             parents.append(parent_name)
             parent_ids.append(parent_index)
-            demos.append(("NULL", parent_name, "NULL", "NULL", parent_index))
+            demos.append(("NULL", parent_name, set(), "NULL", "NULL", parent_index))
 
         parent_index = parent_index + 1
 
@@ -71,8 +91,7 @@ for parent in parents:
     for child in demos:
         if child[1].startswith(parent + "/"):
             title = child[1][child[1].rfind('/') + 1:]
-            file_output += "  { \"" + child[0] + "\", \"" + title + "\", \"" + child[2] + "\", " + child[3] + ", NULL },\n"
-
+            file_output += "  { \"" + child[0] + "\", \"" + title + "\", " + "(const char*[]) {" + ", ".join(list(map(add_quotes, child[2])) + ["NULL"]) + " }, \"" + child[3] + "\", " + child[4] + ", NULL },\n"
 
     file_output += "  { NULL }\n};\n"
     i = i + 1
@@ -86,9 +105,10 @@ for demo in demos:
     # Do not generate one of these for demos with a parent demo
     if "/" not in demo[1]:
         child_array = "NULL"
-        name = demo[0];
-        title = demo[1];
-        file = demo[2]
+        name = demo[0]
+        title = demo[1]
+        keywords = demo[2]
+        file = demo[3]
         if name != "NULL":
             name = "\"" + name + "\""
         if title != "NULL":
@@ -96,9 +116,9 @@ for demo in demos:
         if file != "NULL":
             file = "\"" + file + "\""
 
-        if demo[4] != -1:
-            child_array = "child" + str(demo[4])
-        file_output += "  { " + name + ", " + title + ", " + file + ", " + demo[3] + ", " + child_array + " },\n"
+        if demo[5] != -1:
+            child_array = "child" + str(demo[5])
+        file_output += "  { " + name + ", " + title + ", " + "(const char*[]) {" + ", ".join(list(map(add_quotes, keywords)) + ["NULL"]) + " }, " + file + ", " + demo[4] + ", " + child_array + " },\n"
 
 file_output += "  { NULL }\n};\n"
 
index 3011c3e890356f17fcdf80ca6c688540d1c15951..40789d773eee78bd6dd633dac91288ed4ebc5243 100644 (file)
@@ -28,6 +28,7 @@ struct _GtkDemo
 
   const char *name;
   const char *title;
+  const char **keywords;
   const char *filename;
   GDoDemoFunc func;
   GListModel *children_model;
@@ -38,6 +39,7 @@ enum {
   PROP_FILENAME,
   PROP_NAME,
   PROP_TITLE,
+  PROP_KEYWORDS,
 
   N_PROPS
 };
@@ -70,6 +72,10 @@ gtk_demo_get_property (GObject    *object,
       g_value_set_string (value, self->title);
       break;
 
+    case PROP_KEYWORDS:
+      g_value_set_boxed (value, self->keywords);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
       break;
@@ -100,6 +106,12 @@ static void gtk_demo_class_init (GtkDemoClass *klass)
                          "title",
                          NULL,
                          G_PARAM_READABLE);
+  properties[PROP_KEYWORDS] =
+    g_param_spec_string ("keywords",
+                         "keywords",
+                         "keywords",
+                         NULL,
+                         G_PARAM_READABLE);
 
   g_object_class_install_properties (gobject_class, N_PROPS, properties);
 }
@@ -691,6 +703,21 @@ filter_demo (GtkDemo *demo)
       if (g_str_match_string (search_needle[i], demo->title, TRUE))
         continue;
 
+      if (demo->keywords)
+        {
+          int j;
+          gboolean found = FALSE;
+
+          for (j = 0; !found && demo->keywords[j]; j++)
+            {
+              if (strstr (demo->keywords[j], search_needle[i]))
+                found = TRUE;
+            }
+
+          if (found)
+            continue;
+        }
+
       return FALSE;
     }
 
@@ -761,7 +788,7 @@ demo_search_changed_cb (GtkSearchEntry *entry,
   g_clear_pointer (&search_needle, g_strfreev);
 
   if (text && *text)
-    search_needle = g_strsplit (text, " ", 0);
+    search_needle = g_str_tokenize_and_fold (text, NULL, NULL);
 
   gtk_filter_changed (filter, GTK_FILTER_CHANGE_DIFFERENT);
 }
@@ -779,6 +806,7 @@ create_demo_model (void)
 
       d->name = demo->name;
       d->title = demo->title;
+      d->keywords = demo->keywords;
       d->filename = demo->filename;
       d->func = demo->func;
 
@@ -794,6 +822,7 @@ create_demo_model (void)
 
               child->name = children->name;
               child->title = children->title;
+              child->keywords = children->keywords;
               child->filename = children->filename;
               child->func = children->func;